package cn.jaye.fabric.application;

import cn.jaye.fabric.application.command.GuessCommand;
import cn.jaye.fabric.application.command.GuessMatchCommand;
import cn.jaye.fabric.common.constant.ExceptionEnum;
import cn.jaye.fabric.common.constant.Global;
import cn.jaye.fabric.common.constant.MicroConstant;
import cn.jaye.fabric.common.exception.ServiceException;
import cn.jaye.fabric.domain.model.Guess;
import cn.jaye.fabric.domain.model.Match;
import cn.jaye.fabric.domain.model.User;
import cn.jaye.fabric.infrastructure.mybatis.impl.GuessRepositoryImpl;
import cn.jaye.fabric.infrastructure.mybatis.impl.MatchRepositoryImpl;
import cn.jaye.fabric.infrastructure.mybatis.impl.UseRepositoryImpl;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpSession;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author Jaye
 * @create 2018-06-04 15:30
 */
@Service
public class GuessApplicationService {

    @Autowired
    private MatchRepositoryImpl matchRepository;

    @Autowired
    private GuessRepositoryImpl guessRepository;

    @Autowired
    private UseRepositoryImpl useRepository;

    @Autowired
    private MicroConstant microConstant;

    @Autowired
    private HttpSession httpSession;


    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    public boolean create(GuessMatchCommand guessMatchCommand) {
        Guess guess = new Guess();
        guess.setMatchId(guessMatchCommand.getMatchId());
        guess.setHostScore(guessMatchCommand.getHostScore());
        guess.setGuestScore(guessMatchCommand.getGuestScore());
        String username = getSessionUser();
        checkUser(username);
        long nowTime = System.currentTimeMillis();
        Match match = matchRepository.selectOne(new EntityWrapper<Match>()
                .eq("match_id", guess.getMatchId())
                .eq("match_state", Global.MATCH_STATE_NORMAL));
        if (null != match) {
            Date playDate = match.getPlayTime();
            long playTime = playDate.getTime();
            long timeDiff = (playTime - nowTime) / 1000;
            if (playTime > nowTime && timeDiff > (microConstant.getGuessCountDownTime() * 60)) {
                guess.setUserName(username);
                if (insertOrUpdateGuess(guess)) {
                    return true;
                } else {
                    throw new ServiceException(ExceptionEnum.MATCH_RECORD);
                }
            } else {
                throw new ServiceException(ExceptionEnum.MATCH_STOP);
            }
        } else {
            throw new ServiceException(ExceptionEnum.MATCH_NOFIND);
        }
    }

    public void guessList(User user, GuessCommand guessCommand) {
//        User user = SystemSession.getUser();
        checkUser(user);
        long nowTime = System.currentTimeMillis();
        List<Guess> guesses = guessCommand.getMatchs();
        for (Guess guess : guesses) {
            Match match = matchRepository.selectOne(new EntityWrapper<Match>()
                    .eq("match_id", guess.getMatchId())
                    .eq("match_state", Global.MATCH_STATE_NORMAL));
            if (null != match) {
                Date playDate = match.getPlayTime();
                long playTime = playDate.getTime();
                long timeDiff = (playTime - nowTime) / 1000;
                if (playTime > nowTime && timeDiff > (microConstant.getGuessCountDownTime() * 60)) {
                    guess.setUserName(user.getUserName());
                    if (insertOrUpdateGuess(guess)) {
                        continue;
                    } else {
                        throw new ServiceException(ExceptionEnum.MATCH_RECORD);
                    }
                } else {
                    continue;
                }
            } else {
                throw new ServiceException(ExceptionEnum.MATCH_NOFIND);
            }
        }
    }

    @Transactional(rollbackFor = Exception.class)
    private boolean insertOrUpdateGuess(Guess guess) {
        Guess oldGuess = guessRepository.selectOne(new EntityWrapper<Guess>()
                .eq("user_name", guess.getUserName())
                .eq("match_id", guess.getMatchId())
                .eq("state", Global.GUESS_STATE_NORMAL));
        if (null == oldGuess) {
            return guessRepository.insert(guess);
        } else {
            return guessRepository.update(guess, new EntityWrapper<Guess>()
                    .eq("user_name", guess.getUserName())
                    .eq("match_id", guess.getMatchId())
                    .eq("state", Global.GUESS_STATE_NORMAL));
        }
    }

    private void checkUser(User user) {
        if (null == user || null == user.getUserName()) {
            throw new ServiceException(ExceptionEnum.USER_NOLOGIN);
        }
    }

    private void checkUser(String username) {
        if (StringUtils.isBlank(username)) {
            throw new ServiceException(ExceptionEnum.USER_NOLOGIN);
        }
    }

    /**
     * 积分榜
     */
    public List<User> listScore() {
        return useRepository.getScoreboard();
    }

    public JSONArray listsScore() {
        return useRepository.listScore();
    }

    public JSONArray listGuessMatch() {
        String username = getSessionUser();
        checkUser(username);
        return guessRepository.guessHistory(username);
    }

    public JSONArray listMyGuess() {

        String username = getSessionUser();
        checkUser(username);
        return useRepository.listMyGuess(username);
    }

    public Map<String, String> infoMyRankAndPoint() {
        String username = getSessionUser();
        if (StringUtils.isBlank(username)) {
            Map<String, String> result = new HashMap<>();
            result.put("rownum", "0");
            result.put("scoreCount", "0");
            return result;
        }
        return useRepository.getMyScore(username);
    }

    public JSONArray listYestTodayScoreCount() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date today = new Date();
        Date yestToday = DateUtils.addDays(today, -1);
        String endDate = sdf.format(today);
        String startDate = sdf.format(yestToday);
        return useRepository.listScoreCountByDate(startDate, endDate);
    }

    public JSONArray listMyAllGuess() {
        String username = getSessionUser();
        return useRepository.listMyAllGuess(username);
    }

    public JSONArray listGuessAllowMatch() {
//        User user = SystemSession.getUser();
        String username = getSessionUser();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date today = new Date();
        Date afterToday = DateUtils.addDays(today, 3);
        String endDate = sdf.format(afterToday);
        String startDate = sdf.format(today);
//        String endDate = "2018-06-17";
//        String startDate = "2018-06-14";
        long diffTime = microConstant.getGuessCountDownTime() * (1000 * 60);
        return matchRepository.listMatchByUserAndDate(diffTime, username, startDate, endDate);
    }

    private String getSessionUser() {
        return (String) httpSession.getAttribute("username");
    }
}
